<template>
	<view :class="{
      'r-popover__wrapper': true,
    }" @click.stop="onClickWrapper">
		<slot v-if="$slots.reference" name="reference"></slot>
	</view>
	<r-animation :duration="duration" :show="show" :customStyle="positionStyle" @open="onOpen" @close="onClose"
		@opened="onOpened" @closed="onClosed">
		<view :class="{
        'r-popover': true,
        [`r-popover--${theme}`]: true,
      }" :style="{
        ...getComponentThemeStyle,
        ...otherStyle,
      }">
			<view v-if="showArrow" :class="{
          'r-popover__arrow': true,
        }" :style="arrowStyle"></view>
			<view :class="{
          'r-popover__content': true,
          [`r-popover__content--${actionsDirection}`]: true,
        }">
				<slot v-if="!!$slots.default"></slot>
				<template v-else>
					<!-- renderAction -->
					<view v-for="(action, index) in actions" :key="index" :class="{
              'r-popover__action': true,
              'r-popover__action--disabled': action.disabled,
              'r-popover__action--with-icon': action.icon,
              'r-hairline--right': actionsDirection === 'horizontal',
              [`${action.className}`]: true,
            }" :style="{
              color: action.color,
            }" @click.stop="onClickAction(action, index)">
						<!-- renderActionContent -->
						<slot v-if="!!$slots.action" :action="action" :index="index"></slot>
						<template v-else>
							<view :class="{
                  'r-popover__action-icon': true,
                }" v-if="action.icon">
								<r-icon :name="action.icon" :prefix="iconPrefix" color="inherit" size="inherit" />
							</view>
							<view :class="{
                  'r-popover__action-text': true,
                  'r-hairline--bottom': actionsDirection === 'vertical',
                }">
								{{ action.text }}
							</view>
						</template>
					</view>
				</template>
			</view>
		</view>
	</r-animation>
</template>
<script>
	export default {
		options: {
			styleIsolation: "shared"
		},
	};
</script>
<script setup>
	import {
		computed,
		ref,
		inject,
		nextTick,
		getCurrentInstance,
		onMounted,
	} from "vue";
	import {
		CONFIG_PROVIDER_KEY
	} from '@/uni_modules/r-utils-constant/js_sdk/index.js';
	import {
		getComponentThemeCssVar
	} from "@/uni_modules/r-theme-base/js_sdk/useComponentTheme.js";
	import {
		GetRect,
	} from "@/uni_modules/r-utils-common/js_sdk/index.js";
	import {
		datas
	} from '../themes/index.js';
	const {
		proxy
	} = getCurrentInstance();
	const emit = defineEmits([
		"select",
		"update:show",
		"open",
		"opened",
		"close",
		"closed",
	]);
	const props = defineProps({
		// 是否展示气泡弹出层
		show: {
			type: Boolean,
			default: false,
		},
		//   选项列表
		actions: {
			type: Array,
			default: () => [],
		},
		//   选项列表的排列方向，可选值为 horizontal
		actionsDirection: {
			type: String,
			default: "vertical",
		},
		//   弹出位置 top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end
		placement: {
			type: String,
			default: "bottom",
		},
		//   主题风格，可选值为 dark
		theme: {
			type: String,
			default: "light",
		},

		//   动画时长，单位秒，设置为 0 可以禁用动画
		duration: {
			type: Number,
			default: 300,
		},

		//   是否展示小箭头
		showArrow: {
			type: Boolean,
			default: true,
		},
		//   是否在点击选项后关闭
		closeOnClickAction: {
			type: Boolean,
			default: true,
		},

		//   图标类名前缀，等同于 r-icon 组件的 class-prefix 属性
		iconPrefix: {
			type: String,
			default: "van-icon",
		},
		//层级
		zIndex: {
			type: Number,
			default: 2000,
		},
		//弹出框与内容之间的距离
		gap: {
			style: String,
			default: "8rpx",
		},
		//  r-theme 主题名称
		themeName: {
			type: String,
			default: "default",
		},
	});

	const componentsName = "r-popover";
	const themeInject = inject(CONFIG_PROVIDER_KEY, {});

	const getComponentThemeStyle = computed(() => {
		let themeName = props.themeName;

		if (themeInject?.value?.themeName) {
			//传递过来的有就用传递了
			themeName = themeInject?.value?.themeName;
		}
		if (props.themeName != "default") {
			//单独设置了组件的 就用单独设置的
			themeName = props.themeName;
		}

		return {
			...getComponentThemeCssVar(themeName, "r-base", datas.value),
			...getComponentThemeCssVar(themeName, componentsName, datas.value),
		};
	});
	const show = computed({
		get: () => props.show,
		set: (val) => {
			emit("update:show", val);
		},
	});
	const wrapperRect = ref({});
	const contentRect = ref({});
	const onOpen = () => {
		getConentRect();
		emit("open");
	};
	const onClose = () => {
		emit("close");
	};
	const onOpened = () => {
		emit("opened");
	};
	const onClosed = () => {
		emit("closed");
	};
	const positionStyle = computed(() => {
		const cssVar = {
			position: "relative",
			zIndex: props.zIndex,
		};
		const wrapperRectWidth = wrapperRect.value?.width || 0;
		const wrapperRectHeight = wrapperRect.value?.height || 0;
		const contentRectWidth = contentRect.value?.width || 0;
		const contentRectHeight = contentRect.value?.height || 0;
		const gap = props.gap;
		switch (props.placement) {
			case "bottom":
				cssVar.top = gap;
				cssVar.left = `${(wrapperRectWidth - contentRectWidth) / 2}px`;
				break;

			case "bottom-start":
				cssVar.top = gap;
				break;

			case "bottom-end":
				cssVar.top = gap;
				cssVar.left = `${wrapperRectWidth - contentRectWidth}px`;
				break;

			case "top":
				cssVar.top = `calc(${-wrapperRectHeight - contentRectHeight}px - ${
        props.showArrow ? "var(--r-popover-arrow-size)" : 0
      } - ${gap})`;

				cssVar.marginLeft = `${(wrapperRectWidth - contentRectWidth) / 2}px`;
				break;

			case "top-start":
				cssVar.top = `calc(${-wrapperRectHeight - contentRectHeight}px - ${
        props.showArrow ? "var(--r-popover-arrow-size)" : 0
      } - ${gap})`;
				break;

			case "top-end":
				cssVar.top = `calc(${-wrapperRectHeight - contentRectHeight}px - ${
        props.showArrow ? "var(--r-popover-arrow-size)" : 0
      } - ${gap})`;

				cssVar.marginLeft = `${wrapperRectWidth - contentRectWidth}px`;
				break;

			case "left":
				cssVar.left = `calc(${-contentRectWidth}px - ${
        props.showArrow ? "var(--r-popover-arrow-size)" : 0
      } - ${gap})`;

				cssVar.top = `calc((${-wrapperRectHeight - contentRectHeight}px ) / 2)`;

				break;

			case "left-start":
				cssVar.left = `calc(${-contentRectWidth}px - ${
        props.showArrow ? "var(--r-popover-arrow-size)" : 0
      } - ${gap})`;

				cssVar.top = `${-wrapperRectHeight}px `;

				break;

			case "left-end":
				cssVar.left = `calc(${-contentRectWidth}px - ${
        props.showArrow ? "var(--r-popover-arrow-size)" : 0
      } - ${gap})`;

				cssVar.top = `${-contentRectHeight}px `;

				break;

			case "right":
				cssVar.left = `calc(${wrapperRectWidth}px  + ${gap})`;

				cssVar.top = `calc((${-wrapperRectHeight - contentRectHeight}px ) / 2)`;

				break;

			case "right-start":
				cssVar.left = `calc(${wrapperRectWidth}px  + ${gap})`;

				cssVar.top = `${-wrapperRectHeight}px `;

				break;
			case "right-end":
				cssVar.left = `calc(${wrapperRectWidth}px  + ${gap})`;

				cssVar.top = `${-contentRectHeight}px `;

				break;
		}

		return cssVar;
	});
	const otherStyle = computed(() => {
		let cssVar = {};
		switch (props.placement) {
			case "top":
				cssVar["transform-origin"] = "50% 100%";
				cssVar["margin-bottom"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;

			case "top-start":
				cssVar["transform-origin"] = "0 100%";
				cssVar["margin-bottom"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;

			case "top-end":
				cssVar["transform-origin"] = "100% 100%";
				cssVar["margin-bottom"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;

			case "bottom":
				cssVar["transform-origin"] = "50% 0";
				cssVar["margin-top"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;

			case "bottom-start":
				cssVar["transform-origin"] = "0 0";
				cssVar["margin-top"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;
			case "bottom-end":
				cssVar["transform-origin"] = "100% 0";
				cssVar["margin-top"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;

			case "left":
				cssVar["transform-origin"] = "100% 50%";
				cssVar["margin-right"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;
			case "left-start":
				cssVar["transform-origin"] = "100% 0";
				cssVar["margin-right"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;
			case "left-end":
				cssVar["transform-origin"] = "100% 100%";
				cssVar["margin-right"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;

			case "right":
				cssVar["transform-origin"] = "0 50%";
				cssVar["margin-left"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;
			case "right-start":
				cssVar["transform-origin"] = "0 0";
				cssVar["margin-left"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;
			case "right-end":
				cssVar["transform-origin"] = "0 100%";
				cssVar["margin-left"] = props.showArrow ?
					"var(--r-popover-arrow-size)" :
					0;
				break;
		}

		return cssVar;
	});
	const arrowStyle = computed(() => {
		let cssVar = {};
		//   top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end
		if (["top", "top-start", "top-end"].includes(props.placement)) {
			cssVar["bottom"] = 0;
			cssVar["border-top-color"] = "currentColor";
			cssVar["border-bottom-width"] = 0;
			cssVar["margin-bottom"] = `calc(var(--r-popover-arrow-size) * -1)`;

			if (props.placement == "top") {
				cssVar["left"] = "50%";
				cssVar["transform"] = "translateX(-50%)";
			} else if (props.placement == "top-start") {
				cssVar["left"] = "var(--r-padding-md)";
			} else if (props.placement == "top-end") {
				cssVar["right"] = "var(--r-padding-md)";
			}
		} else if (["left", "left-start", "left-end"].includes(props.placement)) {
			cssVar["right"] = 0;
			cssVar["border-left-color"] = "currentColor";
			cssVar["border-right-width"] = 0;
			cssVar["margin-right"] = `calc(var(--r-popover-arrow-size) * -1)`;

			if (props.placement == "left") {
				cssVar["top"] = "50%";
				cssVar["transform"] = " translateY(-50%)";
			} else if (props.placement == "left-start") {
				cssVar["top"] = "var(--r-padding-md)";
			} else if (props.placement == "left-end") {
				cssVar["bottom"] = "var(--r-padding-md)";
			}
		} else if (["right", "right-start", "right-end"].includes(props.placement)) {
			cssVar["left"] = 0;
			cssVar["border-right-color"] = "currentColor";
			cssVar["border-left-width"] = 0;
			cssVar["margin-left"] = `calc(var(--r-popover-arrow-size) * -1)`;

			if (props.placement == "right") {
				cssVar["top"] = "50%";
				cssVar["transform"] = " translateY(-50%)";
			} else if (props.placement == "right-start") {
				cssVar["top"] = "var(--r-padding-md)";
			} else if (props.placement == "right-end") {
				cssVar["bottom"] = "var(--r-padding-md)";
			}
		} else if (
			["bottom", "bottom-start", "bottom-end"].includes(props.placement)
		) {
			cssVar["top"] = 0;
			cssVar["border-bottom-color"] = "currentColor";
			cssVar["border-top-width"] = 0;
			cssVar["margin-top"] = `calc(var(--r-popover-arrow-size) * -1)`;

			if (props.placement == "bottom") {
				cssVar["left"] = "50%";
				cssVar["transform"] = " translateX(-50%)";
			} else if (props.placement == "bottom-start") {
				cssVar["left"] = "var(--r-padding-md)";
			} else if (props.placement == "bottom-end") {
				cssVar["right"] = "var(--r-padding-md)";
			}
		}

		return cssVar;
	});
	const onClickAction = (action, index) => {
		if (action.disabled) {
			return;
		}

		emit("select", action, index);

		if (props.closeOnClickAction) {
			show.value = false;
		}
	};

	const onClickWrapper = () => {
		show.value = !show.value;
	};
	const getConentRect = () => {
		nextTick(async () => {
			wrapperRect.value = await GetRect(".r-popover__wrapper", proxy);
			contentRect.value = await GetRect(".r-popover", proxy);
		});
	};

	defineExpose({
		getConentRect,
	});
</script>
<style lang="scss" scoped>
	.r-popover {
		position: absolute;
		overflow: visible;
		background-color: transparent;
		transition: opacity 0.15s, transform 0.15s;

		&__wrapper {
			display: inline-block;
		}

		&__arrow {
			position: absolute;
			width: 0;
			height: 0;
			border-color: transparent;
			border-style: solid;
			border-width: var(--r-popover-arrow-size);
		}

		&__content {
			overflow: hidden;
			border-radius: var(--r-popover-radius);

			&--horizontal {
				display: flex;
				width: max-content;

				.r-popover__action {
					flex: none;
					width: auto;
					height: var(--r-popover-horizontal-action-height);
					padding: 0 var(--r-padding-sm);

					&:last-child::after {
						display: none;
					}

					&-icon {
						margin-right: var(--r-padding-base);
						font-size: var(--r-popover-horizontal-action-icon-size);
					}
				}
			}
		}

		&__action {
			position: relative;
			display: flex;
			align-items: center;
			box-sizing: border-box;
			width: var(--r-popover-action-width);
			height: var(--r-popover-action-height);
			padding: 0 var(--r-padding-md);
			font-size: var(--r-popover-action-font-size);
			line-height: var(--r-line-height-md);
			cursor: pointer;

			&:last-child {
				.r-popover__action-text::after {
					display: none;
				}
			}

			&-text {
				display: flex;
				flex: 1;
				align-items: center;
				justify-content: center;
				height: 100%;
			}

			&-icon {
				margin-right: var(--r-padding-xs);
				font-size: var(--r-popover-action-icon-size);
			}

			&--with-icon {
				.r-popover__action-text {
					justify-content: flex-start;
				}
			}
		}

		&--light {
			color: var(--r-popover-light-text-color);

			.r-popover__content {
				background: var(--r-popover-light-background);
				box-shadow: 0 2px 12px rgba(50, 50, 51, 0.12);
			}

			.r-popover__arrow {
				color: var(--r-popover-light-background);
			}

			.r-popover__action {
				&:active {
					background-color: var(--r-active-color);
				}

				&--disabled {
					color: var(--r-popover-light-action-disabled-text-color);
					cursor: not-allowed;

					&:active {
						background-color: transparent;
					}
				}
			}
		}

		&--dark {
			color: var(--r-popover-dark-text-color);

			.r-popover__content {
				background: var(--r-popover-dark-background);
			}

			.r-popover__arrow {
				color: var(--r-popover-dark-background);
			}

			.r-popover__action {
				&:active {
					background-color: rgba(0, 0, 0, 0.2);
				}

				&--disabled {
					color: var(--r-popover-dark-action-disabled-text-color);

					&:active {
						background-color: transparent;
					}
				}
			}

			.r-popover__action-text {
				&::after {
					border-color: var(--r-gray-7);
				}
			}
		}
	}

	.r-hairline--right {
		border-right: solid 1px var(--r-border-color);
	}

	.r-hairline--bottom {
		border-bottom: solid 1px var(--r-border-color);
	}
</style>